<template>
  <div class="zoom-container">
    <ToolbarButton
      type="button"
      icon="i-ri-subtract-line"
      :disabled="currentZoom <= minZoom"
      title="减小缩放"
      hideText
      shortcut="Ctrl+ -"
      @click="handleDecrease"
    />
    <div class="zoom-slider-wrapper">
      <input
        ref="sliderRef"
        v-model.number="zoomValue"
        type="range"
        :min="minZoom"
        :max="maxZoom"
        :step="step"
        class="zoom-slider"
        @input="handleSliderInput"
        @change="handleSliderChange"
      />
    </div>
    <ToolbarButton
      type="button"
      icon="i-ri-add-line"
      :disabled="currentZoom >= maxZoom"
      title="增大缩放"
      hideText
      shortcut="Ctrl+ +"
      @click="handleIncrease"
    />
  </div>
</template>

<script setup lang="ts">
import {
  inject,
  computed,
  ref,
  watch,
  onMounted,
  onBeforeUnmount,
  nextTick,
  type Ref,
} from "vue";
import { useThrottleFn } from "@vueuse/core";
import tippy, { type Instance as TippyInstance } from "tippy.js";
import "tippy.js/dist/tippy.css";
import ToolbarButton from "../../button/index.vue";
import type { PageOption } from "../../../types";
import type { EditorProps } from "../../../types";
import { useHotkeys } from "../../../utils";

defineOptions({
  name: "ZoomContainer",
});

const pageOptions = inject<Ref<PageOption>>("page");
const editorProps = inject<EditorProps | undefined>("editorProps", undefined);

// 缩放范围配置
const minZoom = 20;
const maxZoom = 500;
const step = 10;

// Slider 引用
const sliderRef = ref<HTMLInputElement>();
let sliderTippyInstance: TippyInstance | null = null;

// 当前缩放级别
const currentZoom = computed(() => {
  return pageOptions?.value?.zoomLevel || 100;
});

// 获取提示文本
const getTooltipText = (zoom: number) => {
  return `当前缩放比例：${zoom}%`;
};

// 获取当前主题
const getCurrentTheme = (): "light" | "dark" => {
  // 优先使用 editorProps 中的 theme
  if (editorProps?.theme) {
    return editorProps.theme;
  }
  // 如果没有配置，检查 HTML 元素的 data-theme 属性
  const htmlTheme = document.querySelector("html")?.getAttribute("data-theme");
  if (htmlTheme === "dark") {
    return "dark";
  }
  return "light";
};

// 滑块的值（用于双向绑定）
const zoomValue = ref(currentZoom.value);

watch(
  currentZoom,
  (newZoom) => {
    zoomValue.value = newZoom;
  },
  { immediate: true }
);

// 使用节流优化滑块拖拽时的更新频率（每 50ms 最多执行一次）
const updateZoomLevel = (value: number) => {
  if (pageOptions?.value) {
    pageOptions.value.zoomLevel = value;
    pageOptions.value.autoWidth = false;
  }

  if (sliderTippyInstance) {
    sliderTippyInstance.setContent(getTooltipText(value));
  }
};

const throttledUpdateZoom = useThrottleFn(updateZoomLevel, 50);

const handleSliderInput = (event: Event) => {
  const target = event.target as HTMLInputElement;
  const value = Number.parseInt(target.value, 10);
  zoomValue.value = value;
  // 使用节流更新缩放级别
  throttledUpdateZoom(value);
};

const handleSliderChange = (event: Event) => {
  const target = event.target as HTMLInputElement;
  const value = Number.parseInt(target.value, 10);

  const clampedValue = Math.max(minZoom, Math.min(maxZoom, value));

  if (pageOptions?.value) {
    pageOptions.value.zoomLevel = clampedValue;
    pageOptions.value.autoWidth = false;
  }
};

// 页面缩放 - 放大（使用节流，限制快速连续按键的更新频率）
const _zoomIn = () => {
  if (!pageOptions?.value) return;
  if (pageOptions.value.zoomLevel && pageOptions.value.zoomLevel < 500) {
    pageOptions.value.zoomLevel += 10;
    pageOptions.value.autoWidth = false;
  }
};

// 页面缩放 - 缩小（使用节流，限制快速连续按键的更新频率）
const _zoomOut = () => {
  if (!pageOptions?.value) return;
  if (pageOptions.value.zoomLevel && pageOptions.value.zoomLevel > 20) {
    pageOptions.value.zoomLevel -= 10;
    pageOptions.value.autoWidth = false;
  }
};

// 使用节流优化快捷键操作（每 100ms 最多执行一次，避免快速按键导致性能问题）
const zoomIn = useThrottleFn(_zoomIn, 100);
const zoomOut = useThrottleFn(_zoomOut, 100);

// 处理减小缩放
const handleDecrease = zoomOut;

// 处理增大缩放
const handleIncrease = zoomIn;

let isDragging = false;
let hideTimer: ReturnType<typeof setTimeout> | null = null;

// 快捷键解绑函数
let unbindZoomIn: (() => void) | null = null;
let unbindZoomOut: (() => void) | null = null;

const preventBrowserZoom = (event: KeyboardEvent) => {
  if (event.ctrlKey || event.metaKey) {
    if (event.key === "-" || event.code === "Minus") {
      event.preventDefault();
      return true;
    }
    if (
      event.key === "+" ||
      event.code === "Equal" ||
      event.code === "NumpadAdd" ||
      (event.key === "=" && event.shiftKey)
    ) {
      event.preventDefault();
      return true;
    }
  }
  return false;
};

onMounted(() => {
  window.addEventListener("keydown", preventBrowserZoom, true);

  // 绑定快捷键（只绑定一次）
  if (!unbindZoomOut) {
    unbindZoomOut = useHotkeys("ctrl+-,command+-", zoomOut);
  }
  if (!unbindZoomIn) {
    unbindZoomIn = useHotkeys("ctrl+=,command+=", zoomIn);
  }

  nextTick(() => {
    if (sliderRef.value) {
      const theme = getCurrentTheme();
      sliderTippyInstance = tippy(sliderRef.value, {
        content: getTooltipText(currentZoom.value),
        placement: "top",
        theme: theme,
        trigger: "manual", // 手动触发，只在拖拽或 hover 时显示
      });

      const sliderEl = sliderRef.value;

      // 保存事件处理函数引用以便清理
      const handleMouseEnter = () => {
        if (sliderTippyInstance) {
          sliderTippyInstance.show();
        }
      };
      const handleMouseLeave = () => {
        if (sliderTippyInstance && !isDragging) {
          sliderTippyInstance.hide();
        }
      };
      const handleMouseDown = () => {
        isDragging = true;
        if (sliderTippyInstance) {
          sliderTippyInstance.show();
        }
      };
      const handleMouseUp = () => {
        isDragging = false;
        if (hideTimer) {
          clearTimeout(hideTimer);
        }
        hideTimer = setTimeout(() => {
          if (sliderTippyInstance && sliderEl && !sliderEl.matches(":hover")) {
            sliderTippyInstance.hide();
          }
        }, 300);
      };

      sliderEl.addEventListener("mouseenter", handleMouseEnter);
      sliderEl.addEventListener("mouseleave", handleMouseLeave);
      sliderEl.addEventListener("mousedown", handleMouseDown);
      sliderEl.addEventListener("mouseup", handleMouseUp);

      // 保存引用以便清理
      (sliderEl as any)._zoomEventHandlers = {
        mouseenter: handleMouseEnter,
        mouseleave: handleMouseLeave,
        mousedown: handleMouseDown,
        mouseup: handleMouseUp,
      };
    }
  });

  watch(
    () => currentZoom.value,
    (newZoom) => {
      if (sliderTippyInstance) {
        sliderTippyInstance.setContent(getTooltipText(newZoom));
      }
    }
  );

  watch(
    () => editorProps?.theme,
    () => {
      if (sliderTippyInstance) {
        const theme = getCurrentTheme();
        sliderTippyInstance.setProps({ theme: theme });
      }
    }
  );

  watch(
    () => zoomValue.value,
    () => {
      if (sliderRef.value && sliderTippyInstance && isDragging) {
        // 拖拽时显示提示
        sliderTippyInstance.show();
      }
    }
  );
});

// 清理 Tippy 实例和事件监听器
onBeforeUnmount(() => {
  if (hideTimer) {
    clearTimeout(hideTimer);
    hideTimer = null;
  }
  
  // 清理 slider 事件监听器
  if (sliderRef.value && (sliderRef.value as any)._zoomEventHandlers) {
    const handlers = (sliderRef.value as any)._zoomEventHandlers;
    sliderRef.value.removeEventListener("mouseenter", handlers.mouseenter);
    sliderRef.value.removeEventListener("mouseleave", handlers.mouseleave);
    sliderRef.value.removeEventListener("mousedown", handlers.mousedown);
    sliderRef.value.removeEventListener("mouseup", handlers.mouseup);
    delete (sliderRef.value as any)._zoomEventHandlers;
  }
  
  sliderTippyInstance?.destroy();
  sliderTippyInstance = null;

  // 移除浏览器缩放阻止监听器
  window.removeEventListener("keydown", preventBrowserZoom, true);

  // 解绑快捷键
  if (unbindZoomIn) {
    unbindZoomIn();
    unbindZoomIn = null;
  }
  if (unbindZoomOut) {
    unbindZoomOut();
    unbindZoomOut = null;
  }
});
</script>

<style scoped lang="scss">
.zoom-container {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 4px;
  height: 100%;
  min-width: 0; // 防止 flex 子元素溢出
}

// 按钮样式由 ToolbarButton 组件提供，这里只保留必要的容器样式
.zoom-container :deep(.toolbar-button-wrapper) {
  flex-shrink: 0;
  position: relative;
  z-index: 0; // 确保按钮在 slider 下方
}

.zoom-slider-wrapper {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 1;
  min-width: 60px;
  max-width: 150px;
  position: relative;
  z-index: 1; // 确保 slider 在按钮上方
}

.zoom-slider {
  flex: 1;
  width: 100%;
  min-width: 0; // 允许 slider 缩小到小于默认最小宽度
  height: 3px;
  -webkit-appearance: none;
  appearance: none;
  background: var(--editor-border-color-light, #e4e7ed);
  border-radius: 2px;
  outline: none;
  cursor: pointer;
  position: relative;

  &::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 12px;
    height: 12px;
    background: var(--editor-primary-color, #409eff);
    border-radius: 50%;
    cursor: pointer;
    transition: all 0.2s;

    &:hover {
      transform: scale(1.1);
      background: var(--editor-primary-color-hover, #66b1ff);
    }
  }

  &::-moz-range-thumb {
    width: 12px;
    height: 12px;
    background: var(--editor-primary-color, #409eff);
    border-radius: 50%;
    cursor: pointer;
    border: none;
    transition: all 0.2s;

    &:hover {
      transform: scale(1.1);
      background: var(--editor-primary-color-hover, #66b1ff);
    }
  }
}

.zoom-display {
  flex-shrink: 0;
  min-width: 36px;
  font-size: 11px;
  font-weight: 500;
  color: var(--editor-text-color);
  text-align: center;
  user-select: none;
  line-height: 1;
}
</style>
